
pub mod console {
    pub fn print(s: &str)
    {
        print!("{}", s);
    }

    pub fn println(s: &str)
    {
        println!("{}", s);
    }

    pub fn flush()
    {
        ::std::io::Write::flush(&mut ::std::io::stdout())
            .expect("::std::io::Write::flush error");
    }

    pub fn print_and_flush(s: &str)
    {
        print!("{}", s);
        ::std::io::Write::flush(&mut ::std::io::stdout())
            .expect("::std::io::Write::flush error");
    }

    pub fn println_and_flush(s: &str)
    {
        println!("{}", s);
        ::std::io::Write::flush(&mut ::std::io::stdout())
            .expect("::std::io::Write::flush error");
    }

    pub fn read() -> String
    {
        let mut buf = String::new();
        ::std::io::stdin().read_line(&mut buf)
            .expect("::std::io::stdin().read_line error");
        buf.trim().to_string()
    }

    /**
     * 返回值会带\n
    */
    pub fn read_line() -> String
    {
        let mut buf = String::new();
        ::std::io::stdin().read_line(&mut buf)
            .expect("::std::io::stdin().read_line error");
        buf
    }
}


pub mod fs {

    pub fn create_file_and_write(path: &str, buf: &[u8])
    {
        match ::std::fs::File::create(path) {
            Ok(result) => {
                let mut f = result;
                ::std::io::Write::write_all(&mut f, buf)
                    .expect("::std::io::Write::write_all error");
            },
            Err(e) => {
                eprintln!("{}", e);
            }
        }
    }


    pub fn read_string(path: &str) -> Option<String>
    {
        let mut f = match ::std::fs::File::open(path) {
            Ok(file) => file,
            Err(e) => {
                eprintln!("{}", e);
                return Option::None;
            }
        };
        let mut text = String::new();
        match ::std::io::Read::read_to_string(&mut f, &mut text)
        {
            Err(e) => {
                eprintln!("{}", e);
                Option::None
            },
            Ok(_) => {
                Option::Some(text)
            }
        }
    }
}


pub trait ToF64
{
    fn to_f64(&self) -> f64;
}
/* 为String增加to_f64 */
impl super::common::ToF64 for String {
    fn to_f64(&self) -> f64 {
        let value = self.parse::<f64>();
        match value {
            Ok(v) => v,
            Err(e) => {
                println!("{:?}", e);
                return 0.0;
            },
        }
    }
}
/* 为&str增加to_f64 */
impl super::common::ToF64 for str {
    fn to_f64(&self) -> f64 {
        self.to_string().to_f64()
    }
}



pub trait FromInput {
    fn from_input() -> Self;
}

pub trait Name
{
    fn name(&self) -> &String;
    fn get_name(&self) -> &String;
}


pub trait Json
    where Self: ::serde::Serialize, Self: for <'de> ::serde::Deserialize <'de>
{
    fn from_json(path: &str) -> Option<Self>
    {
        let option = fs::read_string(path);
        if option.is_none() { return Option::None; }
        let text = option.unwrap();
        match ::serde_json::from_str(&text) {
            Ok(json) => {
                let object:Self = json;
                Option::Some(object)
            },
            Err(e) => {
                eprintln!("{}", e);
                Option::None
            },
        }
    }


    fn write_json(&self, path: &str)
    {
        let object_str = ::serde_json::to_string_pretty(self).unwrap();
        fs::create_file_and_write(path, &object_str.as_bytes());
    }
    
}


pub trait MultiJson
    where Self: Sized
{
    /* 建议如果没加载到文件则返回结果为Option::None */
    fn from_multi_json(dir_path: &str) -> Option<Self>;
    fn write_multi_json(&self, dir_path: &str);
}

/* 给 HashMap<String, T> 类型实现 MultiJson 特性 */
impl <T> MultiJson for ::std::collections::HashMap<String, T>
    where T: Name + Json
{
    /* 没有读取到文件数据则返回 Option::None */
    fn from_multi_json(dir_path: &str) -> Option<Self>
    {
        //读取文件夹
        let result = match ::std::fs::read_dir(dir_path) {
            Ok(dir) => Option::Some(dir),
            Err(e) => {
                eprintln!("{}", e);
                eprintln!("文件夹读取失败");
                return Option::None;
            }
        };
        if result.is_none(){ return Option::None; }


        //读取文件夹条目
        let dir = result.unwrap();
        let mut map = Self::new();
        for result in dir
        {
            if result.is_err()
            {
                eprintln!("entry is err");
                eprintln!("{}", result.unwrap_err());
                continue;//读取下一个条目
            }
            
            let entry = result.unwrap();
            let path = entry.path();
            let path_str = path.to_str().unwrap();
            if entry.file_type().unwrap().is_dir() {//应该读取文件夹里的json文件，如果不是json文件而是文件夹，应该读取下一个条目
                eprintln!("{}不是文件", path_str);
                continue;//读取下一个条目
            }

            println!("read {}", path_str);
            if path_str.ends_with(".json")
            {
                let option = T::from_json(path_str);
                if option.is_none()
                {
                    eprintln!("option is none");
                    eprintln!("{}读取错误", path_str);
                    continue;//读取下一个文件
                }
                let data = option.unwrap();
                map.insert(data.get_name().to_string(), data);
                println!("数据{}已加载", path_str);
            }
            else {
                eprintln!("{}不是json文件", path_str);
                continue;// 读取下一个文件
            }
        };
        if map.is_empty() { return Option::None; }
        Option::Some(map)
    }

    fn write_multi_json(&self, dir_path: &str) {
        for (name, data) in self
        {
            let path = format!("{}/{}.json", dir_path, name);
            data.write_json(path.as_str());
        }
    }
}




pub trait DataTransfer<T>
{
    fn transfer(&mut self) -> T;
}

